#include "../Field/Field3D.h"

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;


template<class Type>
Field3D<Type>::Field3D() : Field<Type>()
{
    this->data_=NULL;
}

template<class Type>
Field3D<Type>::Field3D(vector<int> dims) : Field<Type>(dims)
{
    this->data_=NULL;
    allocate_dims(dims);
}

template<class Type>
Field3D<Type>::Field3D(vector<int> dims, string name) : Field<Type>(dims, name)
{
    this->data_=NULL;
    allocate_dims(dims);
}

template<class Type>
Field3D<Type>::~Field3D()
{
    delete [] this->data_;
    for (int i = 0; i < this->dims_[0]; i++) delete [] data_3D[i];
    delete [] this->data_3D;

}

template<class Type>
void Field3D<Type>::allocate_dims(std::vector<int> dims )
{
    this->dims_=dims;

    if (this->dims_.size()!=3)
    {
        log_error<<"Alloc d dim must be 3 : " << dims.size();
    }

    if (this->data_)
    {
        log_debug<<"this->data_ not NULL "<<this->data_;
        delete [] this->data_;
    }


    this->data_ = new Type[this->dims_[0] * this->dims_[1] * this->dims_[2]];

    data_3D= new Type**[this->dims_[0]];

    for(int i = 0; i < this->dims_[0]; i++)
    {
        data_3D[i]= new Type*[this->dims_[1]];
        for (int j = 0; j < this->dims_[1]; j++)
        {
            data_3D[i][j] = this->data_ + i * this->dims_[1] * this->dims_[2] + j * this->dims_[2];
        }
    }

    this->dims_global_ = this->dims_[0] * this->dims_[1] * this->dims_[2];

}

template<class Type>
Field3D<Type>& Field3D<Type>::operator=(const Field3D<Type>& field3D)
{
    if (this->dims_[0] != field3D.dims_[0] || this->dims_[1] != field3D.dims_[1] || this->dims_[2] != field3D.dims_[2])
    {
        log_error<<"dims not equal";
    }

    for(int i = 0; i < this->dims_global_; i++)
    {
        this->data_[i] = field3D.data_[i];
    }
    return *this;
}

template class Field3D<double>;
template class Field3D<int>;
